---
--类名: TeamManager.lua
--创建日期: 2017-3-11
--创建人: 陈小虎
--功能描述: 
--修改内容:
--修改日期:2018-6-1
--修改人:galileoliu
--修改备注: 
--

local TeamManager = class("TeamManager")

local SAFE_DISTANCE = 700

local MathFloor = math.floor
local MathAbs = math.abs
local NodeGetPositionX = cc.Node.getPositionX


function TeamManager:ctor()
    cc(self):addComponent("components.behavior.EventProtocol"):exportMethods()

    self:init()
end

function TeamManager:init()
    self._myTeamLeaderId = 0  -- 0表示没有队伍
    self._myTeamEntities = {} -- 我的队伍数据
    self._myTeamIndex = 0  -- 0表示没有跟随队伍,其他值表示在队伍中的站位
end

function TeamManager:clear()
    self._myTeamLeaderId = 0
    self._myTeamEntities = {}
    self._myTeamIndex = 0
end

function TeamManager:updateTeamEntities()
    self:clear()

    -- 根据更新的entity数据，重新组装队伍信息
    local otherEntities = FieldManager:getOtherEntities()
    local myTeamModel = app:getInst("TeamModel")
    if myTeamModel and myTeamModel:hasTeam() then
        -- 如果我在队伍中
        self._myTeamLeaderId = myTeamModel:getLeaderUid()
        if self._myTeamLeaderId == UD:getUid()
          or myTeamModel:isWithTeam(UD:getUid()) then
            -- 如果我跟随队伍，组装队伍数据
            table.insert(self._myTeamEntities, UD:getUid())
            for entityId, _ in pairs(otherEntities) do
                if self._myTeamLeaderId == entityId
                  or myTeamModel:isWithTeam(entityId) then
                    table.insert(self._myTeamEntities, entityId)
                end
            end
            self:sortEntities()
            for i, entityId in ipairs(self._myTeamEntities) do
                if entityId == UD:getUid() then
                    self._myTeamIndex = i
                end
            end
        end
    end

    -- dump(self._myTeamEntities, "_myTeamEntities")
end

function TeamManager:sortEntities()
    table.sort(self._myTeamEntities, function(a, b)
        if a == self._myTeamLeaderId then
            return true
        elseif b == self._myTeamLeaderId then
            return false
        else
            -- 机器人都真人后面，机器人id是负数
            if a * b < 0 then
                -- 一机器人一真人
                return a > 0
            else
                return a < b
            end
        end
    end)
end

function TeamManager:isEnitityInMyTeam(targetEntityId)
    for i, entityId in ipairs(self._myTeamEntities) do
        if entityId == targetEntityId then
            return true, i
        end
    end
    return false
end

function TeamManager:getTeamCharacters()
    local result = {}
    local character
    for _, entityId in ipairs(self._myTeamEntities) do
        character = FieldManager:getCharacterByUid(entityId)
        if character then
            table.insert(result, character)
        end
    end
    return result
end

function TeamManager:getTeamLeaderId()
    return self._myTeamLeaderId
end

function TeamManager:resetTeamMemberPositionToLeaderForStory()
    if self._myTeamLeaderId > 0 then
        local myTeamModel = app:getInst("TeamModel")
        if self._myTeamLeaderId == UD:getUid()
          or myTeamModel:isWithTeam(UD:getUid()) then
            local leaderCharacter = FieldManager:getCharacterByUid(self._myTeamLeaderId)
            if leaderCharacter == nil then return end

            local count = 1
            local leaderX = NodeGetPositionX(leaderCharacter)
            local leaderDir = leaderCharacter:getDirection()
            local memberCharacter
            for _, entityId in ipairs(self._myTeamEntities) do
                local memberX = leaderX
                if entityId ~= self._myTeamLeaderId then
                    memberCharacter = FieldManager:getCharacterByUid(entityId)
                    if memberCharacter ~= nil then
                        if leaderDir == memberCharacter.DIR_LEFT then
                            memberX = leaderX + count * Constant.TeamCharacterInterval
                            local maxX = leaderCharacter:getLineMaxX()
                            if memberX > maxX then
                                memberX = maxX
                            end
                        else
                            memberX = leaderX - count * Constant.TeamCharacterInterval
                            local minX = leaderCharacter:getLineMinX()
                            if memberX < minX then
                                memberX = minX
                            end
                        end

                        count = count + 1

                        if memberX ~= NodeGetPositionX(memberCharacter) then
                            memberCharacter:setTargetX(memberX)
                            memberCharacter:showLocationX(memberX)
                        end
                    end
                end
            end
        end
    end
end

function TeamManager:getFollowX(startX, teamIndex, isLeft, maxX, minX)
    local targetX = startX
    if isLeft then
        targetX = startX + (teamIndex - 1) * Constant.TeamCharacterInterval
    else
        targetX = startX - (teamIndex - 1) * Constant.TeamCharacterInterval
    end
    targetX = (targetX > maxX) and maxX or targetX
    targetX = (targetX < minX) and minX or targetX
    return targetX
end

function TeamManager:updateFollow(leaderCharacter, character, teamIndex)
    if not leaderCharacter or not character then return end
    local line = leaderCharacter.LINE_2
    local leaderDir = leaderCharacter:getDirection()
    local leaderX = MathFloor(NodeGetPositionX(leaderCharacter))
    local characterX = MathFloor(NodeGetPositionX(character))
    local targetX = self:getFollowX(leaderX, teamIndex, leaderDir == character.DIR_LEFT, leaderCharacter:getLineMaxX(), leaderCharacter:getLineMinX())
    if character:getLine() ~= line then
        MapManager:getMap():changeLine(character, line)
    end
    character:setSpeed(leaderCharacter:getSpeed())
    if MathAbs(targetX - characterX) <= SAFE_DISTANCE then
        character:setTargetX(targetX)
    else
        character:showLocationX(targetX)
        character:setDirection(leaderDir)
        if character:getUid() == UD:getUid() then
            MapManager:initCamera()
        end
    end
end

function TeamManager:autoTeamMemberGetOffRide()
    if self._myTeamLeaderId > 0 then
        local myTeamModel = app:getInst("TeamModel")
        if self._myTeamLeaderId == UD:getUid()
          or myTeamModel:isWithTeam(UD:getUid()) then
            local leaderCharacter = FieldManager:getCharacterByUid(self._myTeamLeaderId)
            if leaderCharacter and not leaderCharacter:isGetOnRide() then
                local memberCharacter
                for _, entityId in ipairs(self._myTeamEntities) do
                    if entityId ~= self._myTeamLeaderId then
                        memberCharacter = FieldManager:getCharacterByUid(entityId)
                        if memberCharacter then
                            memberCharacter:getOffRide()
                        end
                    end
                end
            end
        end
    end
end

function TeamManager:resetTeamPosition(destX)
    if self._myTeamLeaderId > 0 then
        local myTeamModel = app:getInst("TeamModel")
        if self._myTeamLeaderId == UD:getUid()
          or myTeamModel:isWithTeam(UD:getUid()) then
            local leaderCharacter = FieldManager:getCharacterByUid(self._myTeamLeaderId)
            if leaderCharacter then
                leaderCharacter:showLocationX(destX)
                leaderCharacter:setTargetX(destX)
                local leaderEntity = FieldManager:getEntityById(self._myTeamLeaderId)
                if leaderEntity then
                    if leaderEntity:isFaceToLeft() then
                        leaderCharacter:faceToLeft()
                    else
                        leaderCharacter:faceToRight()
                    end
                end

                local leaderDir = leaderCharacter:getDirection()
                for i, entityId in ipairs(self._myTeamEntities) do
                    local character = FieldManager:getCharacterByUid(entityId)
                    if character then
                        local fx = self:getFollowX(destX, i, leaderDir == character.DIR_LEFT, leaderCharacter:getLineMaxX(), leaderCharacter:getLineMinX())
                        character:showLocationX(fx)
                        character:setTargetX(fx)
                    end
                end
            end

            MapManager:initCamera()
        end
    end
end

function TeamManager:updateTeamPosition()
    if self._myTeamLeaderId > 0 then
        local myTeamModel = app:getInst("TeamModel")
        if self._myTeamLeaderId == UD:getUid()
          or myTeamModel:isWithTeam(UD:getUid()) then
            local leaderCharacter = FieldManager:getCharacterByUid(self._myTeamLeaderId)
            local character
            for i, entityId in ipairs(self._myTeamEntities) do
                if entityId ~= self._myTeamLeaderId then
                    character = FieldManager:getCharacterByUid(entityId)
                    self:updateFollow(leaderCharacter, character, i)
                end
            end
        end
    end
end

return TeamManager